/**
 * Excel操作工具类，定义了多个Excel操作方法，在构造本类时需在调用构造方法的时候传一个Excel的File参数进去
 * @author Maxj,2009-10-30
 */
package platform.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public class OperateExcel {
	private Workbook wb; // 可以理解为一个Excel文件

	/**
	 * 构造方法,参数为File（Excel文件）
	 * 
	 * @throws BiffException,
	 *             IOException
	 */
	public OperateExcel(File file) throws BiffException, IOException {
		wb = Workbook.getWorkbook(file);
	}

	/**
	 * 释放内存
	 */
	public void clear() {
		wb.close();
	}

	/**
	 * 行数
	 * 
	 * @param sheetIndex
	 * @return
	 */
	public int getRows(int sheetIndex) {
		Sheet s = wb.getSheet(sheetIndex);
		return s.getRows();
	}

	/**
	 * 列数
	 * 
	 * @param sheetIndex
	 * @return
	 */
	public int getColumns(int sheetIndex) {
		Sheet s = wb.getSheet(sheetIndex);
		return s.getColumns();
	}

	/**
	 * 获取指定sheet中的指定起始读取位置的所有数据，返回一个String的集合
	 * 
	 * @param sheetIndex
	 *            根据顺序获取sheet，0是第一个
	 * @param rowStart
	 *            读取时的起始行数，0是第一行
	 * @param colStart
	 *            读取时的起始列数，0是第一列
	 * @return 一个按顺序存放了每一个Cell中的数据（String类型）的集合
	 */
	public List getCellsBySheetIndexToString(int sheetIndex, int rowStart,
			int colStart) {
		Sheet s = wb.getSheet(sheetIndex);
		List list = new ArrayList();
		if (s != null) {
			for (int i = rowStart; i < s.getRows(); i++) {
				for (int j = colStart; j < s.getColumns(); j++) {
					Cell c = s.getCell(j, i);
					list.add(c.getContents());
				}
			}
		}
		return list;
	}

	/**
	 * 获取指定sheet中的指定起始读取位置的所有数据，返回一个List的集合
	 * 
	 * @param sheetIndex
	 *            根据顺序获取sheet，0是第一个
	 * @param rowStart
	 *            读取时的起始行数，0是第一行
	 * @param colStart
	 *            读取时的起始列数，0是第一列
	 * @return 一个存放了每一行数据集合（List类型）的一个大集合
	 */
	public List getCellsBySheetIndexToList(int sheetIndex, int rowStart,
			int colStart) {
		Sheet s = wb.getSheet(sheetIndex);
		List list = new ArrayList();
		if (s != null) {
			for (int i = rowStart; i < s.getRows(); i++) {
				List listRow = new ArrayList();
				for (int j = colStart; j < s.getColumns(); j++) {
					Cell c = s.getCell(j, i);
					listRow.add(c.getContents());
				}
				list.add(listRow);
			}
		}
		return list;
	}

	/**
	 * 获取指定页签名称的指定起始读取位置的所有数据，返回一个List的集合
	 * 
	 * @param sheetName
	 *            根据页签的名称获取
	 * @param rowStart
	 *            读取时的起始行数，0是第一行
	 * @param colStart
	 *            读取时的起始列数，0是第一列
	 * @return 一个存放了每一行数据集合（List类型）的一个大集合
	 */
	public List getCellsBySheetName(String sheetName, int rowStart, int colStart) {
		Sheet s = wb.getSheet(sheetName);
		List list = new ArrayList();
		if (s != null) {
			for (int i = rowStart; i < s.getRows(); i++) {
				List listRow = new ArrayList();
				for (int j = colStart; j < s.getColumns(); j++) {
					Cell c = s.getCell(j, i);
					listRow.add(c.getContents());
				}
				list.add(listRow);
			}
		}
		return list;
	}

	/**
	 * 验证导入数据的表头是否合法(注意：此方法只能判断表头为一行或两行的数据)
	 * 
	 * @param headArray
	 *            传入表头数组
	 * @param headIndex
	 *            要验证的表头的位置，一行时为数字，多行用：起始行@结束行
	 * @param sheetName
	 *            根据页签的名称获得表头验证
	 * @return 表头验证通过返回true，验证不通过返回false
	 * @throws Exception
	 */
	public boolean checkHead(String[] headArray, String headIndex,
			String sheetName) throws Exception {
		boolean checkPass = true; // 默认设置表头信息验证通过，是合法的表头
		Sheet sheet = null;
		// 如果传入的页签名称为1，默认获取第一个页签(sheetIndex==0)的表头
		if ("1".equals(sheetName)) {
			sheet = wb.getSheet(0);
		} else {
			sheet = wb.getSheet(sheetName);
		}
		// 注意：学习-->sheet.getCell(x,y)第y行的第x列
		if (sheet == null) {
			checkPass = false;
			throw new Exception("读取Excel文件的信息出错,请检查导入文件的页签信息!");
		} else {
			if (headArray.length > 0) {
				int i = 0;
				List list = new ArrayList();
				// 获取当前页签内数据的列数
				int colNum = sheet.getColumns();
				// 表头有一行以上的数据
				if (headIndex.indexOf("@") > 0) {
					String[] s = headIndex.split("@");
					i = Integer.parseInt(s[0]);
					// 从多行中获取表头的数据并放入List中
					for (int j = 0; j < colNum; j++) {
						Cell cell = sheet.getCell(j, i);
						Cell cellNext = sheet.getCell(j, i + 1);
						if (cell.getContents().equals("")) {
							if (cellNext.getContents().equals("")) {
								continue;
							} else {
								list.add(cellNext.getContents());
							}
						} else {
							list.add(cell.getContents());
							if (cellNext.getContents().equals("")) {
								continue;
							} else {
								list.add(cellNext.getContents());
							}
						}
					}
				} else { // 表头只有一行数据
					i = Integer.parseInt(headIndex);
					for (int k = 0; k < colNum; k++) {
						Cell c = sheet.getCell(k, i);
						list.add(c.getContents());
					}
				}
				// 首先验证表头的个数是否和传入的表头的个数一致
				if (list.size() != headArray.length) {
					checkPass = false; // 表头长度不合法
					throw new Exception("您导入的文件页签名称为：" + sheetName
							+ " 的表头信息不合法!请检查或重新下载业务报表,操作数据后再进行导入操作!");
				} else {
					// 接着验证表头的内容是否和传入的表头内容相同
					for (int m = 0; m < headArray.length; m++) {
						if (!(headArray[m]
								.equals(((String) list.get(m)).trim()))) {
							checkPass = false;
							throw new Exception("您上传的Excel文件 页签名称为："
									+ sheetName + " 中表头的:" + list.get(m)
									+ " 列与系统中定义的表头：" + headArray[m]
									+ " 列不相等,请检查Excel文件!");
						} else
							continue;
					}
				}
			} else {
				checkPass = false;
				throw new Exception("您导入的文件页签名称为：" + sheetName
						+ " 的系统定义表头信息数据有误,请重新执行导入操作或联系系统管理人员!");
			}
		}
		return checkPass;
	}

	/**
	 * 读取excel中sheetName工作区中从rowsStart行到rowsEnd行,colsStart列到colsEnd列中的数据:如2维数组,i[][]
	 * 
	 * @param sheetName
	 *            根据页签的名称获取
	 * @param rowsStart
	 *            从第几行开始读取，为-1 代表从第一行开始读取
	 * @param colsStart
	 *            从第几列开始读取，为-1 代表从第一列开始读取
	 * @param rowsEnd
	 *            读取到第几行结束，为-1或者超出最大行 代表读取全部行
	 * @param colsEnd
	 *            读取到第几列结束，为-1或者超出最大列 代表读取全部列
	 * @return List
	 */
	public List read(String sheetName, int rowsStart, int colsStart,
			int rowsEnd, int colsEnd) {
		List listData = new ArrayList();
		int rstart = rowsStart;
		int rend = rowsEnd;
		int cstart = colsStart;
		int cend = colsEnd;
		Sheet sheet = wb.getSheet(sheetName);
		if (sheet != null) {
			if (rstart == -1) {
				rstart = 0;
			}
			if (cstart == -1) {
				cstart = 0;
			}
			if (rend == -1 || rend > sheet.getRows()) {
				rend = sheet.getRows();
			} else {
				rend = rend + 1;
			}
			if (cend == -1 || cend > sheet.getColumns()) {
				cend = sheet.getColumns();
			} else {
				cend = cend + 1;
			}
			listData = readExcelFileData(sheet, rstart, cstart, rend, cend);
		}
		return listData;
	}

	/**
	 * 读取excel中sheetIndex工作区中从rowsStart行到rowsEnd行,colsStart列到colsEnd列中的数据:如2维数组,i[][]
	 * 
	 * @param sheetIndex
	 *            根据页签的index获取sheet，0是第一个
	 * @param rowsStart
	 *            从第几行开始读取，为-1 代表从第一行开始读取
	 * @param colsStart
	 *            从第几列开始读取，为-1 代表从第一列开始读取
	 * @param rowsEnd
	 *            读取到第几行结束，为-1或者超出最大行 代表读取全部行
	 * @param colsEnd
	 *            读取到第几列结束，为-1或者超出最大列 代表读取全部列
	 * @return List
	 */
	public List read(int sheetIndex, int rowsStart, int colsStart, int rowsEnd,
			int colsEnd) {
		List listData = new ArrayList();
		int rstart = rowsStart;
		int rend = rowsEnd;
		int cstart = colsStart;
		int cend = colsEnd;
		Sheet sheet = wb.getSheet(sheetIndex);
		if (sheet != null) {
			if (rstart == -1) {
				rstart = 0;
			}
			if (cstart == -1) {
				cstart = 0;
			}
			if (rend == -1 || rend > sheet.getRows()) {
				rend = sheet.getRows();
			} else {
				rend = rend + 1;
			}
			if (cend == -1 || cend > sheet.getColumns()) {
				cend = sheet.getColumns();
			} else {
				cend = cend + 1;
			}
			listData = readExcelFileData(sheet, rstart, cstart, rend, cend);
		}
		return listData;
	}

	/**
	 * 开始读取指定开始行、开始列、结束行、结束列位置的数据
	 * 
	 * @param sheet
	 *            指定的页签
	 * @param rowsStart
	 *            开始行位置
	 * @param colsStart
	 *            开始列位置
	 * @param rowsEnd
	 *            结束行位置
	 * @param colsEnd
	 *            结束列位置
	 * @return
	 */
	private List readExcelFileData(Sheet sheet, int rowsStart, int colsStart,
			int rowsEnd, int colsEnd) {
		List datas = new ArrayList();
		try {
			// 按照总行数循环
			for (int i = rowsStart; i < rowsEnd; i++) {
				List rows = new ArrayList();
				// 按照总列数循环
				for (int j = colsStart; j < colsEnd; j++) {
					Cell cellData = sheet.getCell(j, i);
					rows.add(cellData.getContents());
				}
				datas.add(rows);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return datas;
	}
}